/*********************************************************
**                                                      **
**                 liblife.h v1.0.0                     **
**                                                      **
** A library to handle the data from Windows link files **
**                                                      **
**             Copyright Paul Tew 2011                  **
**                                                      **
** Structures                                           **
** -----------                                          **
** LIF       - Link File data                           **
** LIF_A     - ASCII representation of a LIF            **
**                                                      **
** Major Functions:                                     **
** ----------------                                     **
** test_link(FILE*)                                     **
**       Returns 0 if the file pointed to by fp is a    **
**       Windows Link file -1 if not.                   **
**                                                      **
** get_lif(FILE*, int, LIF*)                            **
**       Populates LIF with the decoded link file data  **
**                                                      **
** get_lif_a(LIF*, LIF_A*)                              **
**       Converts the LIF to a readable version         **
**                                                      **
*********************************************************/

/*
This file is part of Lifer.

    Lifer is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    Lifer is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with Lifer.  If not, see <http://www.gnu.org/licenses/>.
*/

#include <inttypes.h>
#include <stdio.h>
#include <time.h>
#include <wchar.h>

/******************************************************************************/
//Minor Structure Definitions

// extradata types
enum EDTYPES
{
  EMPTY                        = 0,
  CONSOLE_PROPS                = 1,
  CONSOLE_FE_PROPS             = 2,
  DARWIN_PROPS                 = 4,
  ENVIRONMENT_PROPS            = 8,
  ICON_ENVIRONMENT_PROPS       = 16,
  KNOWN_FOLDER_PROPS           = 32,
  PROPERTY_STORE_PROPS         = 64,
  SHIM_PROPS                   = 128,
  SPECIAL_FOLDER_PROPS         = 256,
  TRACKER_PROPS                = 512,
  VISTA_AND_ABOVE_IDLIST_PROPS = 1024
};

struct LIF_CLSID
{
  uint32_t           Data1;       //32bit Data1         - Represented LE
  uint16_t           Data2;       //16bit Data2         - Represented LE
  uint16_t           Data3;       //16bit Data3         - Represented LE
  unsigned char      Data4hi[2];  //High part of data 4 - Represented BE
  unsigned char      Data4lo[6];  //Low part of data 4  - Represented BE
};

struct LIF_CLSID_A
{
  char               UUID[40];    //UUID Representation
  char               Version[40];
  char               Variant[40]; // 'NCS', 'ITU', 'Microsoft' or 'Future ITU'
  char               Time[30];
  char               Time_long[40];
  char               ClockSeq[10];
  char               Node[20];
};

struct LIF_CONSOLE_PROPS
{
  uint32_t           Size;
  uint32_t           sig;
  //TODO Define this
};

struct LIF_CONSOLE_PROPS_A
{
  char               Size[10];
  char               sig[12];
  //TODO Define this
};

struct LIF_CONSOLE_FE_PROPS
{
  uint32_t           Size;
  uint32_t           sig;
  //TODO Define this
};

struct LIF_CONSOLE_FE_PROPS_A
{
  char               Size[10];
  char               sig[12];
  //TODO Define this
};

struct LIF_DARWIN_PROPS
{
  uint32_t           Size;
  uint32_t           sig;
  //TODO Define this
};

struct LIF_DARWIN_PROPS_A
{
  char               Size[10];
  char               sig[12];
  //TODO Define this
};

struct LIF_ENVIRONMENT_PROPS
{
  uint32_t           Size;
  uint32_t           sig;
  //TODO Define this
};

struct LIF_ENVIRONMENT_PROPS_A
{
  char               Size[10];
  char               sig[12];
  //TODO Define this
};

struct LIF_ICON_ENVIRONMENT_PROPS
{
  uint32_t           Size;
  uint32_t           sig;
  //TODO Define this
};

struct LIF_ICON_ENVIRONMENT_PROPS_A
{
  char               Size[10];
  char               sig[12];
  //TODO Define this
};

struct LIF_KNOWN_FOLDER_PROPS
{
  uint32_t           Size;
  uint32_t           sig;
  struct LIF_CLSID   KFGUID;
  uint32_t           KFOffset;
};

struct LIF_KNOWN_FOLDER_PROPS_A
{
  char                Size[10];
  char                sig[12];
  struct LIF_CLSID_A  KFGUID;
  char                KFOffset[10];
};

struct LIF_PROPERTY_STORE_PROPS
{
  uint32_t           Size;
  uint32_t           sig;
  uint32_t           NumStores;
};

struct LIF_PROPERTY_STORE_PROPS_A
{
  char               Size[10];
  char               sig[12];
  char               NumStores[10];
};

struct LIF_SHIM_PROPS
{
  uint32_t           Size;
  uint32_t           sig;
  wchar_t            LayerName[600];
};

struct LIF_SHIM_PROPS_A
{
  char               Size[10];
  char               sig[12];
  char               LayerName[600];
};

struct LIF_SPECIAL_FOLDER_PROPS
{
  uint32_t           Size;
  uint32_t           sig;
  uint32_t           SpecialFolderID;
  uint32_t           Offset;
};

struct LIF_SPECIAL_FOLDER_PROPS_A
{
  char               Size[10];
  char               sig[12];
  char               SpecialFolderID[10];
  char               Offset[10];
};

struct LIF_TRACKER_PROPS
{
  uint32_t           Size;
  uint32_t           sig;
  uint32_t           Length;
  uint32_t           Version;
  char               MachineID[16]; //NetBios names have a Max of 16 chars
  struct LIF_CLSID   Droid1;
  struct LIF_CLSID   Droid2;
  struct LIF_CLSID   DroidBirth1;
  struct LIF_CLSID   DroidBirth2;
};

struct LIF_TRACKER_PROPS_A
{
  char                Size[10];
  char                sig[12];
  char                Length[10];
  char                Version[10];
  char                MachineID[17];
  struct LIF_CLSID_A  Droid1;
  struct LIF_CLSID_A  Droid2;
  struct LIF_CLSID_A  DroidBirth1;
  struct LIF_CLSID_A  DroidBirth2;
};

struct LIF_VISTA_IDLIST_PROPS
{
  uint32_t           Size;
  uint32_t           sig;
//  struct ITEMID**    Items;      //A variable number of variable length
                                 //structures
  uint16_t           NumItemIDs; //This isn't in the specification but it seemed
                                 // like a good idea to include it.
};

struct LIF_VISTA_IDLIST_PROPS_A
{
  char               Size[10];
  char               sig[12];
//  struct ITEMID_A**  Items;          //A variable number of variable length
                                     //structures
  char               NumItemIDs[10];
};

struct LIF_EXTRA_DATA
{
  uint32_t                             Size;    //Not in the spec
  enum EDTYPES                         edtypes; //Not in the spec & not in
                                                // ASCII version either.
  struct LIF_CONSOLE_PROPS             lcp;
  struct LIF_CONSOLE_FE_PROPS          lcfep;
  struct LIF_DARWIN_PROPS              ldp;
  struct LIF_ENVIRONMENT_PROPS         lep;
  struct LIF_ICON_ENVIRONMENT_PROPS    liep;
  struct LIF_KNOWN_FOLDER_PROPS        lkfp;
  struct LIF_PROPERTY_STORE_PROPS      lpsp;
  struct LIF_SHIM_PROPS                lsp;
  struct LIF_SPECIAL_FOLDER_PROPS      lsfp;
  struct LIF_TRACKER_PROPS             ltp;
  struct LIF_VISTA_IDLIST_PROPS        lvidlp;
  uint32_t                             terminal;
};

struct LIF_EXTRA_DATA_A
{
  char                                   Size[10];
  char                                   edtypes[300];
  struct LIF_CONSOLE_PROPS_A             lcpa;
  struct LIF_CONSOLE_FE_PROPS_A          lcfepa;
  struct LIF_DARWIN_PROPS_A              ldpa;
  struct LIF_ENVIRONMENT_PROPS_A         lepa;
  struct LIF_ICON_ENVIRONMENT_PROPS_A    liepa;
  struct LIF_KNOWN_FOLDER_PROPS_A        lkfpa;
  struct LIF_PROPERTY_STORE_PROPS_A      lpspa;
  struct LIF_SHIM_PROPS_A                lspa;
  struct LIF_SPECIAL_FOLDER_PROPS_A      lsfpa;
  struct LIF_TRACKER_PROPS_A             ltpa;
  struct LIF_VISTA_IDLIST_PROPS_A        lvidlpa;
  char                                   terminal[15];
};

struct LIF_STRINGDATA
{
  uint32_t           Size;          //This isn't in the specification but I've
                                   //included it to help calculate the position
  uint16_t           CountChars[5];
  char               Data[5][300]; //StringData can be any length but I've
                                   //restricted it to returning just 300 chars
};

struct LIF_STRINGDATA_A
{
  char               Size[10];
  char               CountChars[5][10];
  char               Data[5][300];
};

struct LIF_CNR //Common Network Relative Link structure
{
  uint32_t           Size;
  uint32_t           Flags;
  uint32_t           NetNameOffset;
  uint32_t           DeviceNameOffset;
  uint32_t           NetworkProviderType;
  uint32_t           NetNameOffsetU;
  uint32_t           DeviceNameOffsetU;
  char               NetName[300]; //This is probably way in excess of what is
                                  //needed but I can't find any documentation on
                                  //maxima
  char               DeviceName[300]; //Ditto
  wchar_t            NetNameU[300];
  wchar_t            DeviceNameU[300];
};

struct LIF_CNR_A
{
  char               Size[10];
  char               Flags[30];
  char               NetNameOffset[10];
  char               DeviceNameOffset[10];
  char               NetworkProviderType[35];
  char               NetNameOffsetU[10];
  char               DeviceNameOffsetU[10];
  char               NetName[300];
  char               DeviceName[300];
  char               NetNameU[300];
  char               DeviceNameU[300];
};

struct LIF_VOLID
{
  uint32_t           Size;
  uint32_t           DriveType;
  uint32_t           DriveSN; // Drive Serial Number
  uint32_t           VLOffset; // Volume Label Offset
  uint32_t           VLOffsetU; // Optional Unicode Volume Label Offset
  char               VolumeLabel[33];
  wchar_t            VolumeLabelU[33];
};

struct LIF_VOLID_A
{
  char               Size[10];
  char               DriveType[20];
  char               DriveSN[20];
  char               VLOffset[20];
  char               VLOffsetU[20];
  char               VolumeLabel[33];
  char               VolumeLabelU[33];
};

struct VKEY
{
  unsigned char      LowKey;        //Main key pressed
  unsigned char      HighKey;       //Shift, Ctrl or Alt
};

struct LIF_INFO  // Link Info Structure
{
  uint32_t           Size;
  uint32_t           HeaderSize;
  uint32_t           Flags;
  uint32_t           IDOffset; //ID Offset
  uint32_t           LBPOffset; //Local Base Path Offset
  uint32_t           CNRLOffset; //Common Network Relative Link Offset
  uint32_t           CPSOffset; //Common Path Suffix Offset
  uint32_t           LBPOffsetU; //Local Base path Offset (Unicode)
  uint32_t           CPSOffsetU; //Common Path Suffix Offset Unicode
  struct LIF_VOLID   VolID;     //Volume ID structure
  char               LBP[300]; //Local Base Path
  struct LIF_CNR     CNR;      //Common Network Relative Link structure
  char               CPS[100]; //Common Path Suffix
  wchar_t            LBPU[300]; //Local Base Path, Unicode version
  wchar_t            CPSU[100]; //Common Path Suffix, Unicode
};

struct LIF_INFO_A
{
  char               Size[10];
  char               HeaderSize[10];
  char               Flags[100];
  char               IDOffset[10];
  char               LBPOffset[10];
  char               CNRLOffset[10];
  char               CPSOffset[10];
  char               LBPOffsetU[10];
  char               CPSOffsetU[10];
  struct LIF_VOLID_A VolID;
  char               LBP[300]; //Local Base Path
  struct LIF_CNR_A   CNR;
  char               CPS[100]; //Common Path Suffix
  char               LBPU[300]; //Local Base Path, Unicode version
  char               CPSU[100]; //Common Path Suffix, Unicode
};

struct LIF_IDLIST //This is a considerable simplification of the data for IDLIST
                  // and ITEMID which are both contained in this structure.
{
  uint16_t           IDL_size;
//  struct ITEMID**    Items;      //A variable number of variable length
                                 //structures
  uint16_t           NumItemIDs; //This isn't in the specification but it seemed
                                 // like a good idea to include it.
};

struct LIF_IDLIST_A
{
  char               IDL_size[10];
//  struct ITEMID_A**  Items;          //A variable number of variable length
                                     //structures
  char               NumItemIDs[10];
};

struct LIF_HDR
{
  uint32_t           H_size;       //header size     - must be 0x0000004C
  struct LIF_CLSID   CLSID;        //GUID identifier - must be standard
  uint32_t           Flags;        //What can I say? flags!
  uint32_t           Attr;         //File attributes
  int64_t            CrDate;       //Creation Time
  int64_t            AcDate;       //Access Time
  int64_t            WtDate;       //Write Time
  uint32_t           Size;         //File Size
  int32_t            IconIndex;    //Icon Location in a given resource.
  uint32_t           ShowState;    //Starting state for the application.
  struct VKEY        Hotkey;       //Virtual Key to activate this link
  uint16_t           Reserved1;    //Must be 0
  uint32_t           Reserved2;    //Must be 0
  uint32_t           Reserved3;    //Must be 0
};

struct LIF_HDR_A
{
  char               H_size[10];
  char               CLSID[40];
  char               Flags[550];
  char               Attr[250];
  char               CrDate[30];
  char               AcDate[30];
  char               WtDate[30];
  char               CrDate_long[40];
  char               AcDate_long[40];
  char               WtDate_long[40];
  char               Size[25];
  char               IconIndex[25];
  char               ShowState[40];
  char               Hotkey[40];
  char               Reserved1[10];
  char               Reserved2[20];
  char               Reserved3[20];
};

/******************************************************************************/
//Major Structure Definitions

struct LIF
{
  struct LIF_HDR           lh;
  struct LIF_IDLIST        lidl;
  struct LIF_INFO          li;
  struct LIF_STRINGDATA    lsd;
  struct LIF_EXTRA_DATA    led;
};

struct LIF_A
{
  struct LIF_HDR_A         lha;
  struct LIF_IDLIST_A      lidla;
  struct LIF_INFO_A        lia;
  struct LIF_STRINGDATA_A  lsda;
  struct LIF_EXTRA_DATA_A  leda;
};
/******************************************************************************/
//Public Function Declarations

//Tests to see if a file is a link file (0 if it is, < -1 if not)
int test_link(FILE *);
//FILE* is an opened FILE pointer

//fills the LIF structure with data (0 if successful < -1 if not)
//USING THIS FUNCTION REQUIRES THE USE OF free_lif() TO FREE THE MEMORY ONCE
//THE LIF IS NO LONGER REQUIRED
int get_lif(FILE *, int, struct LIF *);
//FILE* is an opened FILE pointer
//int is the size of the opened file
//LIF is a pointer to a struct LIF which will hold the data

//fills LIF_A with the ASCII representation of the LIF
//(0 if successful < -1 if not)
int get_lif_a(struct LIF *, struct LIF_A *);
//LIF must be a filled LIF structure
//LIF_A is an empty LIF_A structure
